<html lang="en-US">

<head>
    
<title>Prometheus 四大度量指标的了解和应用 - 花落雨忧</title>

<meta property="og:title" content="Prometheus 四大度量指标的了解和应用 - 花落雨忧">



    



    
    <meta property="description" content="在上一个章节中我们完成了 Prometheus 的基本概念了解和安装，由于考虑到看我博客的估计是开发向的小伙伴居多，因此没有再更深入。而今天本章节将介绍我们开发用的最多的度量指标，并结合实战对 Metrics 进行使用和细节分析。
[&amp;hellip;] 来自维基百科
[&amp;hellip;] 度量是指对于一个物体或是事件的某个性质给予一个数字，使其可以和其他物体或是事件的相同性质比较。度量可以是对一物 &amp;hellip;">
    <meta property="og:description" content="在上一个章节中我们完成了 Prometheus 的基本概念了解和安装，由于考虑到看我博客的估计是开发向的小伙伴居多，因此没有再更深入。而今天本章节将介绍我们开发用的最多的度量指标，并结合实战对 Metrics 进行使用和细节分析。
[&amp;hellip;] 来自维基百科
[&amp;hellip;] 度量是指对于一个物体或是事件的某个性质给予一个数字，使其可以和其他物体或是事件的相同性质比较。度量可以是对一物 &amp;hellip;">
    






<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="shortcut icon" href="https://www.lican.site/logo/logo.png" type="image/x-icon" />



<link rel="stylesheet" href="/css/style.min.css" />

<link rel="stylesheet" href="/css/reset.min.css" />




<script src="https://www.lican.site/js/highlight.min.js"></script>

<script>
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll();
</script>


<script src="https://www.lican.site/js/jquery.min.js"></script>




<link href="https://www.lican.site/css/hugo-code.min.css" rel="stylesheet" />



    <style>
        .post-content img {
            max-width: 400px;
        }
    </style>
</head>

<body id="period" class="home blog">
    <a class="skip-content" href="#main">Press "Enter" to skip to content</a>
    <div id="overflow-container" class="overflow-container">
        <header class="site-header" id="site-header" role="banner">
    <div class="max-width">
        <div id="title-container" class="title-container">
            <div id="site-title" class="site-title"><a href="/">花落雨忧</a></div>
            <p class="tagline">思所及 力所行 方为真.</p>
        </div>
        
        <div id="menu-primary-container" class="menu-primary-container">
            <div class="icon-container">
            </div>
            <div id="menu-primary" class="menu-container menu-primary" role="navigation">
                <nav class="menu">
                    <ul id="menu-primary-items" class="menu-primary-items">
                        
                        
                        <li id="menu-item-0"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/posts" aria-current="page" tabindex="0">首页</a></li>
                        
                        <li id="menu-item-1"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/tech/" aria-current="page" tabindex="1">技术文档</a></li>
                        
                        <li id="menu-item-2"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/article/" aria-current="page" tabindex="2">文章</a></li>
                        
                        <li id="menu-item-3"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/project/" aria-current="page" tabindex="3">项目</a></li>
                        
                        <li id="menu-item-4"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/about/" aria-current="page" tabindex="4">关于</a></li>
                        
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</header>
        <div id="primary-container" class="primary-container">
            <div class="max-width">
                <section id="main" class="main" role="main">
                    <div id="loop-container" class="loop-container">
                        <div
                            class="post type-post status-publish format-standard hentry entry">
                            <article>
                                <div class="post-container">
                                    <div class="post-header">
                                        <h2 class="post-title">
                                            <a href="/posts/prometheus/2020-05-16-metrics/">Prometheus 四大度量指标的了解和应用</a>
                                        </h2>
                                        
                                        <div class="post-byline">Published on
                                            <a class="date" href="javascript:;">2020/05/16</a>
                                            
                                            
                                            
                                            
                                            
                                        
                                    </div>
                                    <div class="post-content">
                                        <p>在上一个章节中我们完成了 Prometheus 的基本概念了解和安装，由于考虑到看我博客的估计是开发向的小伙伴居多，因此没有再更深入。而今天本章节将介绍我们开发用的最多的度量指标，并结合实战对 Metrics 进行使用和细节分析。</p>
<h2 id="什么是度量指标">什么是度量指标</h2>
<blockquote>
<p>来自维基百科</p>
</blockquote>
<p>度量是指对于一个物体或是事件的某个性质给予一个数字，使其可以和其他物体或是事件的相同性质比较。度量可以是对一物理量（如长度、尺寸或容量等）的估计或测定，也可以是其他较抽象的特质。</p>
<p>简单来讲，也就是数据的量化，形成对应的数据指标。</p>
<h2 id="prometheus-的指标格式">Prometheus 的指标格式</h2>
<p>在 Prometheus 中，我们的指标表示格式如下：</p>
<pre><code>&lt;metric name&gt;{&lt;label name&gt;=&lt;label value&gt;, ...}
</code></pre><p>主体为指标名称和标签组成：</p>
<pre><code>api_http_requests_total{method=&quot;POST&quot;, handler=&quot;/eddycjy&quot;}
</code></pre><h2 id="对外提供-metrics-服务">对外提供 metrics 服务</h2>
<p>首先创建一个示例项目：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#a6e22e">engine</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">New</span>()
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/hello&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">Context</span>) {
        <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">StatusOK</span>, <span style="color:#e6db74">&#34;煎鱼&#34;</span>)
    })
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>接下我们需要安装 Prometheus Client SDK，在 Go 语言中对应 <a href="https://github.com/prometheus/client_golang">prometheus/client_golang</a> 库：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ go get github.com/prometheus/client_golang
</code></pre></div><p>然后调用 <code>promhttp.Handler</code> 方法创建对应的 metrics：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#f92672">...</span>
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/metrics&#34;</span>, <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">WrapH</span>(<span style="color:#a6e22e">promhttp</span>.<span style="color:#a6e22e">Handler</span>()))
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>重新启动程序，并访问 <code>http://127.0.0.1:10001/metrics</code>：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.</span>
<span style="color:#75715e"># TYPE go_gc_duration_seconds summary</span>
go_gc_duration_seconds<span style="color:#f92672">{</span>quantile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;0&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">0</span>
go_gc_duration_seconds<span style="color:#f92672">{</span>quantile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;0.25&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">0</span>
go_gc_duration_seconds<span style="color:#f92672">{</span>quantile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;0.5&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">0</span>
go_gc_duration_seconds<span style="color:#f92672">{</span>quantile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;0.75&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">0</span>
go_gc_duration_seconds<span style="color:#f92672">{</span>quantile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;1&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">0</span>
go_gc_duration_seconds_sum <span style="color:#ae81ff">0</span>
go_gc_duration_seconds_count <span style="color:#ae81ff">0</span>
<span style="color:#75715e"># HELP go_goroutines Number of goroutines that currently exist.</span>
<span style="color:#75715e"># TYPE go_goroutines gauge</span>
go_goroutines <span style="color:#ae81ff">8</span>
<span style="color:#75715e"># HELP go_info Information about the Go environment.</span>
<span style="color:#75715e"># TYPE go_info gauge</span>
go_info<span style="color:#f92672">{</span>version<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;go1.14.2&#34;</span><span style="color:#f92672">}</span> <span style="color:#ae81ff">1</span>
<span style="color:#75715e"># HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.</span>
<span style="color:#75715e"># TYPE go_memstats_alloc_bytes gauge</span>
go_memstats_alloc_bytes 2.563056e+06
...
</code></pre></div><p>我们可以聚焦其中一个指标：</p>
<pre><code># HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 8
</code></pre><p>你会发现其具有固定的表示格式，分别是指标的含义、指标的类型、指标的具体字段和数值。而在 <code>promhttp.Handler</code> 方法所暴露出来的 metrics 数值，虽然看似很多，但你认真看一下，可以主体为两块：</p>
<ol>
<li>
<p>go_memstats 开头的指标都是 <a href="https://golang.org/pkg/runtime/#MemStats">runtime.MemStats</a> 的格式化数值。</p>
</li>
<li>
<p>promhttp_metric 开头的指标是 HTTP 服务的状态码统计。</p>
</li>
</ol>
<h2 id="prometheus-四大度量指标的了解和应用">Prometheus 四大度量指标的了解和应用</h2>
<h3 id="counter计数器">Counter（计数器）</h3>
<p>Counter 类型代表一个累积的指标数据，其单调递增，只增不减。在应用场景中，像是请求次数、错误数量等等，就非常适合用 Counter 来做指标类型，另外 Counter 类型，只有在被采集端重新启动时才会归零。</p>
<p>Counter 类型一共包含两个常规方法，如下：</p>
<table>
<thead>
<tr>
<th>方法名</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>Inc</td>
<td>将计数器递增 1。</td>
</tr>
<tr>
<td>Add(float64)</td>
<td>将给定值添加到计数器，如果设置的值 &lt; 0，则发生错误。</td>
</tr>
</tbody>
</table>
<h4 id="实战演练">实战演练</h4>
<p>Counter 类型是单纯的累积类计数，最基础的就是在访问请求的时候进行分类统计，在上文的示例项目中继续添加代码：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">AccessCounter</span> = <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">NewCounterVec</span>(
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">CounterOpts</span>{
        <span style="color:#a6e22e">Name</span>: <span style="color:#e6db74">&#34;api_requests_total&#34;</span>,
    },
    []<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">&#34;method&#34;</span>, <span style="color:#e6db74">&#34;path&#34;</span>},
)

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">init</span>() {
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">MustRegister</span>(<span style="color:#a6e22e">AccessCounter</span>)
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#f92672">...</span>
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/counter&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">Context</span>) {
        <span style="color:#a6e22e">purl</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">RequestURI</span>)
        <span style="color:#a6e22e">AccessCounter</span>.<span style="color:#a6e22e">With</span>(<span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">Labels</span>{
            <span style="color:#e6db74">&#34;method&#34;</span>: <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">Method</span>,
            <span style="color:#e6db74">&#34;path&#34;</span>:   <span style="color:#a6e22e">purl</span>.<span style="color:#a6e22e">Path</span>,
        }).<span style="color:#a6e22e">Add</span>(<span style="color:#ae81ff">1</span>)
    })
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/metrics&#34;</span>, <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">WrapH</span>(<span style="color:#a6e22e">promhttp</span>.<span style="color:#a6e22e">Handler</span>()))
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>这时候我们访问 <code>http://127.0.0.1:10001/counter</code>，就可以发现 metrics +1：</p>
<pre><code># HELP api_requests_total 
# TYPE api_requests_total counter
api_requests_total{method=&quot;GET&quot;,path=&quot;/counter&quot;} 1
</code></pre><p>如果希望对全部请求进行记录和统计，我们可以利用拦截器来实现，但是在添加 Labels 时需要注意一点，就是你所定义的指标 Labels 和实际写入时的 Labels 要对应，否则会造成 panic：</p>
<pre><code>2020/05/17 11:01:06 http: panic serving 127.0.0.1:53393: inconsistent label cardinality: expected 3 label values but got 2 in prometheus.Labels{&quot;method&quot;:&quot;GET&quot;, &quot;path&quot;:&quot;/hello&quot;}
goroutine 51 [running]:
net/http.(*conn).serve.func1(0xc0000ee000)
        /usr/local/Cellar/go/1.14.2_1/libexec/src/net/http/server.go:1772 +0x139
panic(0x16272a0, 0xc00009c130)
        /usr/local/Cellar/go/1.14.2_1/libexec/src/runtime/panic.go:975 +0x3e3
github.com/prometheus/client_golang/prometheus.(*CounterVec).With(0xc0001347e0, 0xc00009a4e0, 0x16ea903, 0x4)
        /Users/eddycjy/go/pkg/mod/github.com/prometheus/client_golang@v1.6.0/prometheus/counter.go:259 +0xc2

</code></pre><h3 id="gauge仪表盘">Gauge（仪表盘）</h3>
<p>Gauge 类型代表一个可以任意变化的指标数据，其可增可减。在应用场景中，像是 Go 应用程序运行时的 Goroutine 的数量就可以用该类型来表示，因为其是浮动的数值，并非固定的，侧重于反馈当前的情况。</p>
<p>Gauge 类型一共包含六个常规方法，如下：</p>
<table>
<thead>
<tr>
<th>方法名</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>Set(float64)</td>
<td>将仪表设置为任意值。</td>
</tr>
<tr>
<td>Inc()</td>
<td>将仪表增加 1。</td>
</tr>
<tr>
<td>Dec()</td>
<td>将仪表减少 1。</td>
</tr>
<tr>
<td>Add(float64)</td>
<td>将给定值添加到仪表，该值如果为负数，那么将导致仪表值减少。</td>
</tr>
<tr>
<td>Sub(float64)</td>
<td>从仪表中减去给定值，该值如果为负数，那么将导致仪表值增加。</td>
</tr>
<tr>
<td>SetToCurrentTime()</td>
<td>将仪表设置为当前Unix时间（以秒为单位）。</td>
</tr>
</tbody>
</table>
<h4 id="实战演练-1">实战演练</h4>
<p>Gauge 类型是每次都重新设置的统计类型，在系统中统计 CPU、Memory 等等时很常见，而在业务场景中，业务队列的数量也可以用 Gauge 来统计，实时观察队列数量，及时发现堆积情况：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">QueueGauge</span> = <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">NewGaugeVec</span>(
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">GaugeOpts</span>{
        <span style="color:#a6e22e">Name</span>: <span style="color:#e6db74">&#34;queue_num_total&#34;</span>,
    },
	[]<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">&#34;name&#34;</span>},
)

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">init</span>() {
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">MustRegister</span>(<span style="color:#a6e22e">AccessCounter</span>)
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#f92672">...</span>
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/queue&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">Context</span>) {
        <span style="color:#a6e22e">num</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Query</span>(<span style="color:#e6db74">&#34;num&#34;</span>)
        <span style="color:#a6e22e">fnum</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strconv</span>.<span style="color:#a6e22e">ParseFloat</span>(<span style="color:#a6e22e">num</span>, <span style="color:#ae81ff">32</span>)
        <span style="color:#a6e22e">QueueGauge</span>.<span style="color:#a6e22e">With</span>(<span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">Labels</span>{<span style="color:#e6db74">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;queue_eddycjy&#34;</span>}).<span style="color:#a6e22e">Set</span>(<span style="color:#a6e22e">fnum</span>)
    })
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/metrics&#34;</span>, <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">WrapH</span>(<span style="color:#a6e22e">promhttp</span>.<span style="color:#a6e22e">Handler</span>()))
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>访问 <code>http://127.0.0.1:10001/queue?num=5</code> 后，再查看 metrics 结果：</p>
<pre><code># HELP queue_num_total 
# TYPE queue_num_total gauge
queue_num_total{name=&quot;queue_eddycjy&quot;} 5
</code></pre><p>另外 Gauge 类型也支持各种增减方法，大家根据实际情况调用即可。</p>
<h3 id="histogram累积直方图">Histogram（累积直方图）</h3>
<p>Histogram 类型将会在一段时间范围内对数据进行采样（通常是请求持续时间或响应大小等等），并将其计入可配置的存储桶（bucket）中，后续可通过指定区间筛选样本，也可以统计样本总数。</p>
<p>简单来讲，也就是在配置 Histogram 类型时，我们会设置分组区间，例如要分析请求的响应时间，我们可以分为 0-100ms，100-500ms，500-1000ms 等等区间段，那么在 metrics 的上报接口中，将会分为多个维度显示统计情况。</p>
<p>Histogram 类型一共包含一个常规方法，如下：</p>
<table>
<thead>
<tr>
<th>方法名</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>Observe(float64)</td>
<td>将一个观察值添加到直方图。</td>
</tr>
</tbody>
</table>
<h4 id="实战演练-2">实战演练</h4>
<p>Histogram 类型在应用场景中非常的常用，因为其代表的就是分组区间的统计，而在分布式场景盛行的现在，链路追踪系统是必不可少的，那么针对不同的链路的分析统计就非常的有必要，例如像是对 RPC、SQL、HTTP、Redis 的 P90、P95、P99 进行计算统计，并且更进一步的做告警，就能够及时的发现应用链路缓慢，进而发现和减少第三方系统的影响。</p>
<p>我们模仿记录 HTTP 调用响应时间的应用场景：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">HttpDurationsHistogram</span> = <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">NewHistogramVec</span>(
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">HistogramOpts</span>{
        <span style="color:#a6e22e">Name</span>:    <span style="color:#e6db74">&#34;http_durations_histogram_seconds&#34;</span>,
        <span style="color:#a6e22e">Buckets</span>: []<span style="color:#66d9ef">float64</span>{<span style="color:#ae81ff">0.2</span>, <span style="color:#ae81ff">0.5</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">30</span>},
    },
    []<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">&#34;path&#34;</span>},
)

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">init</span>() {
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">MustRegister</span>(<span style="color:#a6e22e">HttpDurationsHistogram</span>)
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
	<span style="color:#f92672">...</span>
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/histogram&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">Context</span>) {
        <span style="color:#a6e22e">purl</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">RequestURI</span>)
        <span style="color:#a6e22e">HttpDurationsHistogram</span>.<span style="color:#a6e22e">With</span>(<span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">Labels</span>{<span style="color:#e6db74">&#34;path&#34;</span>: <span style="color:#a6e22e">purl</span>.<span style="color:#a6e22e">Path</span>}).<span style="color:#a6e22e">Observe</span>(float64(<span style="color:#a6e22e">rand</span>.<span style="color:#a6e22e">Intn</span>(<span style="color:#ae81ff">30</span>)))
    })
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/metrics&#34;</span>, <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">WrapH</span>(<span style="color:#a6e22e">promhttp</span>.<span style="color:#a6e22e">Handler</span>()))
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>多次调用 <code>http://127.0.0.1:10001/histogram</code>，查看 metrics：</p>
<pre><code># HELP http_durations_histogram_seconds 
# TYPE http_durations_histogram_seconds histogram
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;0.2&quot;} 1
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;0.5&quot;} 1
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;1&quot;} 3
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;2&quot;} 3
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;5&quot;} 3
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;10&quot;} 3
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;30&quot;} 13
http_durations_histogram_seconds_bucket{path=&quot;/histogram&quot;,le=&quot;+Inf&quot;} 13
http_durations_histogram_seconds_sum{path=&quot;/histogram&quot;} 191
http_durations_histogram_seconds_count{path=&quot;/histogram&quot;} 13
</code></pre><p>我们结合 histogram metrics 的结果来看，可以发现其分为了三个部分：</p>
<ol>
<li>
<p>http_durations_histogram_seconds_bucket：在 Buckets 中你可以发现一共包含 8 个值，分别代表：0-0.2s、0.2-0.5s、0.5-1s、1-2s、2-5s、5-10s、10-30s 以及大于 30s（+Inf），这是我们在 <code>HistogramOpts.Buckets</code> 中所定义的区间值。</p>
</li>
<li>
<p>http_durations_histogram_seconds_sum：调用的总耗时。</p>
</li>
<li>
<p>http_durations_histogram_seconds_count：调用总次数。</p>
</li>
</ol>
<p>Histogram 是一个比较精巧类型，首先 Buckets 的分布区间要根据你的实际应用情况，合理的设置，否则就会出现不均，自然而然 PXX（P95、P99 等）计算也就会有问题，同时在 Grafana 上的绘图也会出现偏差，因此需要在理论上多多理解，然后再进行具体的设置，否则后期改来改去会比较麻烦</p>
<p>同时我们也可以利用 http_durations_histogram_seconds_sum 和 http_durations_histogram_seconds_count 相除得出平均耗时，一举多得。</p>
<h3 id="summary摘要">Summary（摘要）</h3>
<p>Summary 类型将会在一段时间范围内对数据进行采样，但是与 Histogram 类型不同的是 Summary 类型将会存储分位数（在客户端进行计算），而不像 Histogram 类型，根据所设置的区间情况统计存储。</p>
<p>Summary 类型在采样计算后，一共提供三种摘要指标，如下：</p>
<ul>
<li>样本值的分位数分布情况。</li>
<li>所有样本值的大小总和。</li>
<li>样本总数。</li>
</ul>
<p>Summary 类型一共包含一个常规方法，如下：</p>
<table>
<thead>
<tr>
<th>方法名</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>Observe(float64)</td>
<td>将一个观察值添加到摘要。</td>
</tr>
</tbody>
</table>
<h4 id="实战演练-3">实战演练</h4>
<p>Summary 类型主要是</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">HttpDurations</span> = <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">NewSummaryVec</span>(
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">SummaryOpts</span>{
        <span style="color:#a6e22e">Name</span>:       <span style="color:#e6db74">&#34;http_durations_seconds&#34;</span>,
        <span style="color:#a6e22e">Objectives</span>: <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">float64</span>]<span style="color:#66d9ef">float64</span>{<span style="color:#ae81ff">0.5</span>: <span style="color:#ae81ff">0.05</span>, <span style="color:#ae81ff">0.9</span>: <span style="color:#ae81ff">0.01</span>, <span style="color:#ae81ff">0.99</span>: <span style="color:#ae81ff">0.001</span>},
    },
    []<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">&#34;path&#34;</span>},
)

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">init</span>() {
    <span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">MustRegister</span>(<span style="color:#a6e22e">HttpDurations</span>)
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#f92672">...</span>
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/summary&#34;</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">Context</span>) {
        <span style="color:#a6e22e">purl</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">Parse</span>(<span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">RequestURI</span>)
        <span style="color:#a6e22e">HttpDurations</span>.<span style="color:#a6e22e">With</span>(<span style="color:#a6e22e">prometheus</span>.<span style="color:#a6e22e">Labels</span>{<span style="color:#e6db74">&#34;path&#34;</span>: <span style="color:#a6e22e">purl</span>.<span style="color:#a6e22e">Path</span>}).<span style="color:#a6e22e">Observe</span>(float64(<span style="color:#a6e22e">rand</span>.<span style="color:#a6e22e">Intn</span>(<span style="color:#ae81ff">30</span>)))
    })
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">GET</span>(<span style="color:#e6db74">&#34;/metrics&#34;</span>, <span style="color:#a6e22e">gin</span>.<span style="color:#a6e22e">WrapH</span>(<span style="color:#a6e22e">promhttp</span>.<span style="color:#a6e22e">Handler</span>()))
    <span style="color:#a6e22e">engine</span>.<span style="color:#a6e22e">Run</span>(<span style="color:#e6db74">&#34;:10001&#34;</span>)
}
</code></pre></div><p>多次调用 <code>http://127.0.0.1:10001/summary</code>，查看 metrics：</p>
<pre><code># HELP http_durations_seconds 
# TYPE http_durations_seconds summary
http_durations_seconds{path=&quot;/summary&quot;,quantile=&quot;0.5&quot;} 17
http_durations_seconds{path=&quot;/summary&quot;,quantile=&quot;0.9&quot;} 29
http_durations_seconds{path=&quot;/summary&quot;,quantile=&quot;0.99&quot;} 29
http_durations_seconds_sum{path=&quot;/summary&quot;} 85
http_durations_seconds_count{path=&quot;/summary&quot;} 5
</code></pre><p>结合 summary metrics 来看，同样分为了三个部分：</p>
<ol>
<li>
<p>http_durations_seconds：分别是中位数（0.5），9 分位数（0.9）以及 99 分位数（0.99），对应 <code>SummaryOpts.Objectives</code> 中我们所定义的中位数，而各自的意义代表着中位数（0.5）的耗时为 17s，9 分位数为 29s，99 分位数为 29s。</p>
</li>
<li>
<p>http_durations_seconds_sum：调用总耗时。</p>
</li>
<li>
<p>http_durations_seconds_count：调用总次数。</p>
</li>
</ol>
<h2 id="小结">小结</h2>
<p>在本章节中我们介绍并实操了 Prometheus 的四种度量指标类型 Counter、Gauge、Histogram、Summary，这四种度量类型都极具代表性：Counter 是单调递增的计数器，Gauge 是可任意调整数值的仪表盘，Histogram 是分组区间统计，Summary 是中位数统计。</p>
<p>其中 Histogram 和 Summary 具有一定的 “相似” 度，因为在 Histogram 指标中我们可以通过 <code>histogram_quantile</code> 函数计算出分位值，而 Summary 也可以计算分位值，两者区别就在于 Histogram 是在服务端计算的，而 Summary 是在客户端就进行了计算，其一个计算好了再推上去，一个直接推上去，数据维度不一样，可以做的事情也不一样，有利有弊，具体可以根据指标的实际情况做衡量。</p>
<p>另外针对度量指标的命名，这是一个非常多人问的问题，因为命名是一个难题，在这里大家可以参照官方的<a href="https://prometheus.io/docs/practices/naming/">文档</a>建议去针对指标命名就可以了。</p>


                                        
                                        
                                        
                                        <div class="rp4wp-related-posts">
                                            <h3>相关文章</h3>
                                            <ul>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/prometheus/2020-05-16-startup/">Prometheus 快速入门</a>
                                                    </div>
                                                </li>
                                                
                                            </ul>
                                        </div>
                                        
                                        
                                    </div>

                                    
                                    
                                    

                                    
                                    <div class="post-meta">
                                        
                                        
                                        <div class="post-tags">
                                            <ul>
                                            
                                            <li>
                                                <a href="/tags/prometheus" title="View all posts tagged match">prometheus</a>
                                            </li>
                                            
                                            </ul>
                                        </div>
                                        
                                        
                                        <nav class="further-reading">
                                            
                                            <div class="previous">
                                                <span>&lt;&lt; Prev</span>
                                                <a href="https://www.lican.site/posts/prometheus/2020-05-16-startup/"
                                                    rel="prev">Prometheus 快速入门</a> </div>
                                            
                                            
                                            <div class="next">
                                                <span>Next >></span>
                                                <a href="https://www.lican.site/posts/prometheus/2020-05-16-pull/">使用 Prometheus 对 Go 程序进行指标采集</a> 
                                            </div>
                                            
                                        </nav>
                                    </div>
                                    
                                    

                                    
                                    
                                    

                                </div>
                            </article>
                        </div>
                    </div>
                </section>
                <aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
    <h1 class="screen-reader-text">Sidebar</h1>
    

    
    
    <section id="text-2" class="widget widget_text">
        <div class="textwidget">
            
            <div id="profile">
                <div id="profile_picture"><img src="https://www.lican.site/logo/logo.png"></div>
                <div id="profile_intro">
                    <p><span class="name">Lican</span></p>
                    <p class="intro">全栈开发者，爱好造轮子。</p>
                </div>
            </div>
            
            <p>
                <script type="text/javascript">
                    (function ($) {
                        $(document).ready(function () {
                            var menuPrimaryContainer = $('#menu-primary-container');
                            var profile = $('#text-2');
                            $('#toggle-navigation').click(function () {
                                if (menuPrimaryContainer.hasClass('open')) {
                                    profile.removeClass('open');
                                } else {
                                    profile.addClass('open');
                                }
                            });
                        });
                    })(jQuery);
                </script>
            </p>
        </div>
    </section>
    
    
    
    
    
    <section id="text-5" class="widget widget_text">
        <h2 class="widget-title">开源项目</h2>
        <div class="textwidget">
            <div id="projects" style="line-height: 22px;">
                
                <a href="https://github.com/idoubi/gonews"
                    target="_blank">gonews</a>: &nbsp;Daily news for golang<br>
                
                <a href="https://github.com/idoubi/sql2struct"
                    target="_blank">sql2struct</a>: &nbsp;Generate go struct according to SQL<br>
                
                <a href="https://github.com/idoubi/goz"
                    target="_blank">goz</a>: &nbsp;Request library used in golang<br>
                
        </div>
    </section>
    
    

    
    
    
    
    

    
    
    

    
    
    

    
    
    
    
</aside>
            </div>
        </div>

        <footer id="site-footer" class="site-footer" role="contentinfo">
    <div class="max-width">
    </div>
    <div class="footer">
        <div id="footercontent">
            © lican.vip All rights reserved<br/>
            Built with Hugo Theme <a href="https://github.com/idoubi/hugo-theme-period" target="_blank">Period</a>
        </div>
    </div>
</footer>

<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?e8351b6d4626d5881d439ea1f6184baa";
      var s = document.getElementsByTagName("script")[0]; 
      s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    
    </div>
    
</body>

</html>